package me.gavin.net

import android.content.Context
import android.net.ConnectivityManager
import androidx.core.content.getSystemService
import me.gavin.di.instanceHolder
import me.gavin.di.remoteModule
import okhttp3.CacheControl
import okhttp3.Interceptor
import okhttp3.Response
import java.io.IOException

/**
 * OkHttp3 缓存拦截器 使用@[remoteModule]
 *
 * @author gavin.xiong 2017/4/28
 */
class OKHttpCacheInterceptor : Interceptor {

    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request().run {
            return@run when {
                !isNetworkAvailable() -> newBuilder()
                    .cacheControl(CacheControl.FORCE_CACHE)
                    .build()
                header("Cache-Control").isNullOrEmpty() -> newBuilder()
                    .header("Cache-Control", "private, max-stale=1")
                    .build()
                else -> this@run
            }
        }
        val response = chain.proceed(request)
        if (response.code == 504) throw NoCacheException()
        return response.newBuilder()
            .removeHeader("Pragma")
            .build()
    }

    private fun isNetworkAvailable(): Boolean {
        return instanceHolder
            .get<Context>()
            .getSystemService<ConnectivityManager>()
            ?.activeNetworkInfo
            ?.isAvailable ?: false
    }

    companion object {
        val CACHE_CONTROL = "Cache-Control"
        val MAX_STALE = "max-stale=2147483647"
        val FORCE_CACHE = "max-stale=2147483647, only-if-cached" // 强制使用缓存
        val NO_CACHE = "$CACHE_CONTROL: no-cache, no-store, must-revalidate" // 禁用缓存

        fun cacheControl(s: Int, name: Boolean = false): String {
            return "${if (name) "$CACHE_CONTROL: " else ""}max-stale=$s"
        }
    }
}

/**
 * OkHttp3 缓存网络拦截器 使用@[remoteModule]
 * 当服务器返回 Cache-Control: must-revalidate 时使用（慎用）
 *
 * @author gavin.xiong 2017/4/28
 */
class OKHttpCacheNetworkInterceptor : Interceptor {

    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        return chain.proceed(chain.request())
            .newBuilder()
            .removeHeader("Pragma")
            .removeHeader("Cache-Control")
            .build()
    }

}
